<script setup lang="ts">
import { h, onMounted, reactive, ref, VNode } from 'vue';
import { useMessage, NDataTable, DataTableColumns, NTime, NButton, NSpace } from 'naive-ui';
import { getToken } from '../util/token';
import { handleNoToken } from '../util/handler';
import { BuyerSideOrder, queryUserOrders, ORDER_STATUS_STRING, SellerSiderStoreOrder, getNextStatus, changeOrderStatus } from '../api/order';
import statusCode from '../api/statusCode';

const message = useMessage();

const queryAllOrder = async () => {
  const token = getToken();
  if (!token) {
    handleNoToken(message);
    return [];
  }

  try {
    const resp = await queryUserOrders(token);

    if (resp.status == statusCode.SUCCESS) {
      return resp.data;
    } else if (resp.status == statusCode.EMPTY_ORDER) {
      return []; // user has no order
    } else {
      throw new Error(`错误码 ${resp.status}`);
    }
  } catch (error) {
    message.error('' + error);
    return [];
  }
};

const flat = ({ storeName, info }: SellerSiderStoreOrder): Column[] => 
  info.flatMap(item => (
    item.info
      .map(subItem => (
        {
          orderId: item.orderId,
          creationTime: Date.parse(item.creationTime),
          address: item.address,
          storeName,
          productName: subItem.productName,
          color: subItem.color,
          quantity: subItem.goodQuantity,
          unitPrice: subItem.unitPrice,
          status: item.orderStatus
        }
      ))
  ));

type Column = {
  orderId: number;
  creationTime: number;
  address: string;
  storeName: string;
  productName: string;
  color: string;
  quantity: number;
  unitPrice: number;
  status: BuyerSideOrder['orderStatus'];
};

const data = reactive<Column[]>([]);

const loading = ref(false);

const getAllOrders = async () => {
  loading.value = true;

  const orders = await queryAllOrder() as SellerSiderStoreOrder[];

  const cols =
    orders
      .flatMap(order => flat(order))
      .sort((a, b) => b.creationTime - a.creationTime);

  data.length = 0;
  data.push(...cols);

  loading.value = false;
};

onMounted(getAllOrders);

const createColumns = (createActionBtn: (row: Column) => VNode | VNode[]): DataTableColumns<Column> => {
  return [
    {
      title: '下单时间',
      key: 'creationTime',
      render(row) {
        return h(NTime, { time: row.creationTime });
      }
    },
    {
      title: '收货地址',
      key: 'address',
    },
    {
      title: '商店',
      key: 'storeName',
    },
    {
      title: '商品',
      key: 'productName'
    },
    {
      title: '颜色',
      key: 'color'
    },
    {
      className: 'quantity-row',
      title: '数量',
      key: 'quantity'
    },
    {
      title: '金额',
      key: 'price',
      render(row) {
        return h('span', { className: 'price' }, { default: () => (row.unitPrice * row.quantity).toFixed(2) });
      }
    },
    {
      title: '状态',
      key: 'status',
      render(row) {
        return h('span', {}, { default: () => ORDER_STATUS_STRING[row.status] ?? '未知状态' })
      }
    },
    {
      title: '操作',
      key: 'action',
      render(row) {
        return createActionBtn(row);
      }
    }
  ];
};

const changeStatus = async (orderId: number, changeTo: Column['status']) => {
  const token = getToken();
  if (!token) {
    handleNoToken(message);
    return [];
  }

  try {
    const resp = await changeOrderStatus({ orderId, status: changeTo, token });

    if (resp.status == statusCode.SUCCESS) {
      return;
    } else {
      throw new Error(`错误码 ${resp.status}`);
    }
  } catch (error) {
    message.error('' + error);
    return;
  }
};

const createActionBtn = (row: Column) => {
  const createButton = (row: Column, nextStatus: { value: Column['status'], label: string}) =>
    h(
      NButton,
      {
        type: 'default',
        onClick: async () => {
          await changeStatus(row.orderId, nextStatus.value);
          getAllOrders();
        }
      },
      { default: () => nextStatus.label }
    );
  const nextStatus = getNextStatus('seller', row.status);
  if (nextStatus === undefined) return h('span', '');

  if (Array.isArray(nextStatus)) {
    return h(NSpace, {}, { default: () => nextStatus.map(next => createButton(row, next)) });
  } else {
    return createButton(row, nextStatus as Extract<typeof nextStatus, Record<string, unknown>[]>);
  }
};

const columns = createColumns(createActionBtn);
</script>

<template>
  <n-data-table
    :loading="loading"
    :columns="columns"
    :data="data"
  />
</template>

<style scoped>
</style>
